package android.slc.extras.component.tree.ui

import android.os.Bundle
import android.slc.adapter.SelectBox
import android.slc.appbase.ui.vd.BaseListCommonVmBox
import android.slc.core.domain.BundleBuilder
import android.slc.core.vm.SingleLiveEvent
import android.slc.extras.component.tree.config.ConstantsTree
import android.slc.extras.component.tree.entity.SlcTree
import androidx.databinding.ObservableField
import com.blankj.utilcode.util.ArrayUtils
import com.blankj.utilcode.util.CollectionUtils
import java.io.Serializable

/**
 * 多选树列表
 * @Description: T 指的是具体的数据，如选择用户时，部门和用户都实现了SlcTree，TP指的是列表数据，如选择用户时，列表数据是SelectBox包了一层T
 * @Author: sunlunchang
 * @CreateDate: 2021/12/06 下午 2:42
 *
 */
abstract class TreeListMultipleVmBox<T : SlcTree, TP : Serializable> : BaseListCommonVmBox<TP>() {
    //有treeId根据treeId来查询子集
    protected var mTreeId: String = ConstantsTree.VALUE_DEF_TREE_ID
        private set

    //没有treeId就根据leafIdList来查询子集
    protected var mLeafIdList = mutableListOf<Serializable>()
        private set

    //传递过来的已选择的数据，用于在获取列表后进行渲染
    private lateinit var mSelectSrcList: MutableList<T>
    protected val mSelectSrcListReadOnly: List<T> get() = mSelectSrcList
    protected lateinit var mSelectNotParentList: MutableList<T>
        private set

    //父节点传递的bundle用于将部分配置属性传递到下个界面
    lateinit var bundle: Bundle
        private set

    //树名称
    val treeName: String?
        get() = bundle.getString(ConstantsTree.KEY_TREE_NAME)

    //自动保存至ActivityResult
    /*val autoSave2Result: Boolean
        get() = bundle.getBoolean(ConstantsTree.KEY_AUTO_SAVE_2_RESULT, true)*/

    //选择改变通知，一般用于有树导航栏的时候，没有导航栏也可以用，监听的通知后一般用于实时保存至ActivityResult中
    val selectChangeNotify = ObservableField<Void>()

    //显示点击树后的界面
    val showTreeClickUiOf = SingleLiveEvent<Bundle>()

    open fun initVmBox(
        treeId: String,
        selectSrcList: MutableList<T>,
        selectNotParentList: MutableList<T>,
        bundle: Bundle
    ) {
        this.mTreeId = treeId
        //叶子id集合
        bundle.getSerializable(ConstantsTree.KEY_LEAF_ID_LIST)?.let {
            val dataBySelect = it as MutableList<*>
            CollectionUtils.forAllDo(dataBySelect) { _, item ->
                if (item is Serializable) {
                    mLeafIdList.add(item)
                }
            }
        }
        this.mSelectSrcList = selectSrcList
        this.mSelectNotParentList = selectNotParentList
        this.bundle = bundle
    }

    fun select(position: Int, selectBox: SelectBox<*>) {
        selectBox.isChecked = !selectBox.isChecked
        //通知自动保存
        mSelectSrcList.remove(selectBox.data)
        if (selectBox.isChecked) {
            mSelectSrcList.add(selectBox.data as T)
        } else {//如果是取消选择则需要移除没有父类的节点数据
            this.mSelectNotParentList.remove(selectBox.data)
        }
        this.selectChangeNotify.notifyChange()
    }

    fun selectAll(selectAll: Boolean) {
        mSelectSrcList.clear()
        CollectionUtils.forAllDo(this.dataList) { _: Int, item: Serializable ->
            if (item is SelectBox<*>) {
                item.isChecked = selectAll
                if (item.isChecked) {
                    mSelectSrcList.add(item.data as T)
                }
            }
        }
        this.dataListOf.notifyChange()
        //通知自动给保存
        this.selectChangeNotify.notifyChange()
    }


    protected open fun loadMoreTree() {
        /*DeptServiceRepository.list(packId).flatMap(object :
            Function<SlcEntity<List<Dept>>, ObservableSource<SlcEntity<DeptAndUser>>> {
            override fun apply(t: SlcEntity<List<Dept>>): ObservableSource<SlcEntity<DeptAndUser>> {
                return UserServiceRepository.list(packId).map { pageModelSlcEntity ->
                    val slcEntity: SlcEntity<DeptAndUser> =
                        DataTransformUtils.slcEntity2TargetRSlcEntity(pageModelSlcEntity)
                    slcEntity.data = DeptAndUser()
                    slcEntity.data.userList = pageModelSlcEntity.data
                    slcEntity.data.nodeDeptList = t.data
                    return@map slcEntity
                }.to(bindToLifecycle())
            }
        }).map(DeptServiceRepository.data2ListGroup(true, getSelectLevelEntityList(selectSrcList)))
        .map(PageTransformUtils.list2PageModelMap())
            .to(bindToLifecycle())
            .subscribe(listPageWrapper.dataListObserver)*/
    }

    final override fun itemClick(index: Int, data: TP) {
        var dateTree: SlcTree? = null
        if (data is SlcTree) {
            dateTree = data

        } else if (data is SelectBox<*>) {
            dateTree = data.data as SlcTree?
        }
        dateTree?.let {
            when (dateTree.tType) {
                SlcTree.VALUE_TREE -> {
                    treeClick(index, dateTree)
                }
                SlcTree.VALUE_LEAF -> {
                    leafClick(index, dateTree)
                }
            }
        }
    }

    protected open fun treeClick(index: Int, data: SlcTree) {
        this.showTreeClickUiOf.value = BundleBuilder.create().build().apply {
            putAll(this@TreeListMultipleVmBox.bundle)
            putSerializable(ConstantsTree.KEY_TREE_ID, data.tId)
            putString(ConstantsTree.KEY_TREE_NAME, data.tName)
        }
    }

    protected open fun leafClick(index: Int, data: SlcTree) {

    }

    /**
     * 获取已经选择的item
     */
    fun getSelectTreeList(
        vararg alternativeDataList: List<T>?,
        onSelectTreeListByListener: ((alternativeDataList: List<T>, item: T) -> Unit)? = null
    ): MutableList<T> {
        val selectTreeList = mutableListOf<T>()
        selectTreeList.addAll(mSelectSrcList)
        alternativeDataList.let { itAlternativeDataList ->
            ArrayUtils.forAllDo(itAlternativeDataList,
                ArrayUtils.Closure<List<T>?> { _, itemList ->
                    CollectionUtils.forAllDo(itemList) { _, item ->
                        if (!selectTreeList.contains(item)) {
                            selectTreeList.add(item)
                            if (onSelectTreeListByListener != null) {
                                onSelectTreeListByListener(itemList, item)
                            }
                        }
                    }
                })
        }
        return selectTreeList
    }

}